package com.hhc.netty;

import android.util.Log;

import com.example.administrator.androidros.utils.ServerConstants;

import java.util.List;
import java.util.concurrent.TimeUnit;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import io.netty.handler.timeout.IdleStateHandler;

/**
 * Created by huhaichao on 2018/4/9.
 */

public class NettyClient {
    public static final int DISCONNECTION = 0;//断开连接
    public static final int CONNECTING = 1;//正在连接
    public static final int CONNECTED = 2;//连接成功
    private static final String TAG = "hhc";
    public static NettyClient nettyClient = null;
    private int connectState = DISCONNECTION;//连接状态
    private SocketChannel socketChannel = null;
    private EventLoopGroup workerGroup = null;
    private Bootstrap bootstrap = null;
    private ChannelFutureListener listener = new ChannelFutureListener() {
        @Override
        public void operationComplete(ChannelFuture future) throws Exception {
            if (future.isSuccess()) {
                Log.e(TAG, "operationComplete: 连接服务器成功");
                setConnectState(CONNECTED);
                socketChannel = (SocketChannel) future.channel();
            } else {
                Log.e(TAG, "operationComplete: 连接服务器失败");
                setConnectState(DISCONNECTION);
                future.channel().eventLoop().schedule(new Runnable() {
                    @Override
                    public void run() {
                        doConnect();
                    }
                }, 3L, TimeUnit.SECONDS);
            }
        }
    };

    private NettyClient() {
        init();
    }

    public static NettyClient getInstance() {
        if (nettyClient == null) {
            nettyClient = new NettyClient();
        }
        return nettyClient;
    }

    private void init() {
        workerGroup = new NioEventLoopGroup();
        bootstrap = new Bootstrap(); // (1)
        bootstrap.group(workerGroup); // (2)
        bootstrap.channel(NioSocketChannel.class); // (3)
        bootstrap.option(ChannelOption.SO_KEEPALIVE, true); // (4)
        bootstrap.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel channel) throws Exception {
                channel.pipeline().addLast(new IdleStateHandler(0, 5, 0, TimeUnit.SECONDS));//在出现超时事件时会被触发，包括读空闲超时或者写空闲超时
                channel.pipeline().addLast(new ObjectEncoder());//object对象传递
                channel.pipeline().addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null)));
                channel.pipeline().addLast(new NettyClientHandler());
            }
        });
    }

    public void doConnect() {
        if (getConnectState() != CONNECTED) {
            try {
                Log.e(TAG, "doConnect: 正在连接...");
                setConnectState(CONNECTING);
                ChannelFuture f = bootstrap.connect(ServerConstants.NETTY_IP, ServerConstants.NETTY_PORT).sync();
                f.addListener(listener);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //断开连接
    public void disconnect() {
        if (socketChannel != null) {
            socketChannel.closeFuture();
            socketChannel.close();
            socketChannel = null;
        }
        if (workerGroup != null) {
            workerGroup.shutdownGracefully();
            workerGroup = null;
        }
        if (bootstrap != null) {
            bootstrap = null;
        }
        if (nettyClient != null) {
            nettyClient = null;
        }
        setConnectState(DISCONNECTION);
    }

    public int getConnectState() {
        return connectState;
    }

    public void setConnectState(int connectState) {
        this.connectState = connectState;
    }

    public void sendMessage(NettyBaseMsg nettyBaseMsg) {
        if (NettyClient.getInstance().getConnectState() != NettyClient.CONNECTED) {
            doConnect();
        } else {
            socketChannel.writeAndFlush(nettyBaseMsg);
        }
    }

    //获取设备状态
    public void getApplianceStatus(String client_id, String device_id, List<DeviceModel> list) {
        Log.d(TAG, "getApplianceStatus: client:" + client_id);
        Log.d(TAG, "getApplianceStatus: device_id:" + device_id);
        Log.d(TAG, "getApplianceStatus: size:" + list.size());
        NettyAskStatusMsg nettyAskStatusMsg = new NettyAskStatusMsg();
        //基本项:client_id,device_id
        nettyAskStatusMsg.setClientId(client_id);
        nettyAskStatusMsg.setDeviceId(device_id);
        //参数项:需要获取状态的设备列表 list
        for (int i = 0; i < list.size(); i++) {
            list.get(i).setDeviceId(device_id);
        }
        nettyAskStatusMsg.setList(list);
        //获取
        sendMessage(nettyAskStatusMsg);
    }

    //控制设备
    public void controlApplianceStatus(String client_id, String device_id, List<DeviceModel> list) {
        NettyOperationMsg nettyOperationMsg = new NettyOperationMsg();
        //基本项:client_id,device_id
        nettyOperationMsg.setClientId(client_id);
        nettyOperationMsg.setDeviceId(device_id);
        //参数项:需要控制的设备列表 list
        nettyOperationMsg.setList(list);
        //获取
        sendMessage(nettyOperationMsg);
    }
}
